package my.mark.mybaibaoxiang.eventDemo.custom;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

/**
 * @Description: 事件总线核心处理
 * @Author wxming
 * @Date 2019年3月25日 下午12:08:51
 */
@SuppressWarnings("rawtypes")
public class EventHandler {
    private final Logger LOG = LoggerFactory.getLogger(EventHandler.class);
    private final Map<Class<? extends ApplicationEvent>, List<ApplicationListener<? extends ApplicationEvent>>> listeners;
    private final ExecutorService pool;

    public EventHandler(Map<Class<? extends ApplicationEvent>, List<ApplicationListener<? extends ApplicationEvent>>> listeners,
                        ExecutorService pool) {
        this.listeners = listeners;
        this.pool = pool;
    }

    /**
     * 处理总线上的事件
     * 
     * @param event
     */
    @SuppressWarnings("unchecked")
    public void postEvent(final ApplicationEvent event) {
        Collection<ApplicationListener<? extends ApplicationEvent>> listenerList = listeners
            .get(event.getClass());
        if (listenerList != null) {
            for (final ApplicationListener listener : listenerList) {
                // 判定是否执行异步监听
                // 只有在异步监听的情况下才支持Tx事务
                if (null != pool) {
                    pool.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                // 判定是否需要事务支持
                                // TODO 获取该类ApplicationListener listener的第一个入参是ApplicationEvent event类型的方法。
                                Method method = listener.getClass().getDeclaredMethod(
                                    ApplicationListener.class.getDeclaredMethods()[0].getName(),
                                    event.getClass());
                                //TODO 判断该方法是否加了@Tx自定义的事务注解。
                                if (method.isAnnotationPresent(Tx.class)) {
                                    /*Db.tx(new IAtom() {
                                        @Override
                                        public boolean run() throws SQLException {
                                            try {
                                                listener.onApplicationEvent(event);
                                                LOG.debug("Tx Commit.");
                                                return true;
                                            } catch (Exception e) {
                                                LOG.error("事件监听执行失败", e);
                                                LOG.debug("Tx rollback.");
                                                return false;
                                            }
                                        }
                                    });*/
                                } else {
                                    listener.onApplicationEvent(event);
                                }
                            } catch (Exception e) {
                                LOG.error("事件监听执行失败", e);
                            }
                        }
                    });
                } else {
                    try {
                        listener.onApplicationEvent(event);
                    } catch (Exception e) {
                        LOG.error("事件监听执行失败", e);
                    }
                }
            }
        }
    }
}
